<?php
include("config.php");

// 反爬机制配置
$antiSpamConfig = [
    'request_limit' => 10,          // 每分钟请求次数限制
    'block_time' => 15 * 60,        // 封锁时间（秒）
    'check_interval' => 60,         // 检查时间窗口（秒）
    'ip_blacklist_file' => __DIR__ . '/data/ip_blacklist.txt',
    'request_log_file' => __DIR__ . '/data/request_log.json'
];

// 创建数据目录（如果不存在）
$antiSpamDir = dirname($antiSpamConfig['request_log_file']);
if (!file_exists($antiSpamDir)) {
    mkdir($antiSpamDir, 0777, true);
}

// 获取客户端IP地址
function getClientIP() {
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        return $_SERVER['HTTP_CLIENT_IP'];
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
    return $_SERVER['REMOTE_ADDR'];
}

// 检查IP是否在黑名单中
function isIPBlacklisted($ip, $blacklistFile) {
    if (!file_exists($blacklistFile)) return false;
    
    $blacklist = file($blacklistFile, FILE_IGNORE_NEW_LINES);
    return in_array($ip, $blacklist);
}

// 记录请求
function logRequest($ip, $config) {
    $requests = [];
    $file = $config['request_log_file'];
    
    // 读取现有记录
    if (file_exists($file)) {
        $json = file_get_contents($file);
        $requests = json_decode($json, true) ?: [];
    }
    
    // 添加新记录
    $requests[] = [
        'ip' => $ip,
        'time' => time()
    ];
    
    // 只保留指定时间窗口内的记录
    $threshold = time() - $config['check_interval'];
    $requests = array_filter($requests, function($r) use ($threshold) {
        return $r['time'] >= $threshold;
    });
    
    // 保存记录
    file_put_contents($file, json_encode(array_values($requests)));
    
    // 如果请求次数超过限制，将IP加入黑名单
    $ipRequests = array_filter($requests, function($r) use ($ip) {
        return $r['ip'] === $ip;
    });
    
    if (count($ipRequests) >= $config['request_limit']) {
        addToIPBlacklist($ip, $config['ip_blacklist_file']);
        return true; // IP已被封锁
    }
    
    return false;
}

function addToIPBlacklist($ip, $blacklistFile) {
    file_put_contents($blacklistFile, $ip . PHP_EOL, FILE_APPEND);
}

function generateRandomBooks($count = 5) {
    $categories = ['文学', '计算机', '历史', '经济', '哲学', '科技', '教育', '医学'];
    $books = [];
    
    for ($i = 0; $i < $count; $i++) {
        $status = rand(0, 1) ? '可借阅' : '已借出';
        $daysAgo = rand(1, 30);
        $date = date('Y-m-d', strtotime("-$daysAgo days"));
        
        $books[] = [
            'id' => rand(1000, 9999),
            'name' => "图书-" . rand(1, 1000),
            'category' => $categories[array_rand($categories)],
            'author' => "作者-" . rand(1, 100),
            'date' => $date,
            'status' => $status
        ];
    }
    
    return $books;
}

$clientIP = getClientIP();

if (isIPBlacklisted($clientIP, $antiSpamConfig['ip_blacklist_file'])) {
    http_response_code(403);
    die("您的IP已被封锁，请稍后再试。");
}

$isBlocked = logRequest($clientIP, $antiSpamConfig);
if ($isBlocked) {
    http_response_code(403);
    die("检测到异常请求，您的IP已被临时封锁。");
}

if (isset($_POST["search"])) {
    $select_type = $_POST["select_type"];
    $content = $_POST["content"];
    $sql = "select * from info_book where ".$select_type." like '%".$content."%'";
    $info=mysqli_query($connect,$sql);
} else {
    $pagesize=1;
    $pageno=isset($_GET['pageno'])?$_GET['pageno']:1;
    $pageno=empty($pageno)? 1 : $pageno;
    $sql2="select * from info_book";
    $res=mysqli_query($connect,$sql2);
    $recordcount=mysqli_num_rows($res); 
    $pagecount=ceil($recordcount/$pagesize);
    $pageno=$pageno>$pagecount ? $pagecount : $pageno;
    $startno=($pageno-1)*$pagesize;
    $sql3="select * from info_book order by id limit $startno,$pagesize";
    $info=mysqli_query($connect,$sql3);
}
$id=$row['id'];

$randomBooks = generateRandomBooks(5);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图书管理系统 - 数据可视化</title>
  <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link rel="shortcut icon" href="icon/favicon.ico" type="image/x-icon">

  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#3b82f6',
            secondary: '#10b981',
            accent: '#8b5cf6',
            dark: '#1e293b',
            light: '#f8fafc'
          },
          fontFamily: {
            sans: ['Inter', 'system-ui', 'sans-serif'],
          },
        },
      }
    }
  </script>
  
  <style type="text/tailwindcss">
    @layer utilities {
      .content-auto {
        content-visibility: auto;
      }
      .chart-shadow {
        box-shadow: 0 10px 25px -5px rgba(59, 130, 246, 0.1), 0 8px 10px -6px rgba(59, 130, 246, 0.1);
      }
      .card-hover {
        transition: all 0.3s ease;
      }
      .card-hover:hover {
        transform: translateY(-5px);
        box-shadow: 0 20px 25px -5px rgba(59, 130, 246, 0.2), 0 10px 10px -5px rgba(59, 130, 246, 0.1);
      }
    }
  </style>
</head>
<body class="bg-gray-50 text-gray-800 min-h-screen">
 
  <!-- 主要内容 -->
  <main class="container mx-auto px-4 pt-5 pb-12">
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
      <div class="bg-white rounded-xl p-6 shadow-lg card-hover border-l-4 border-primary">
        <div class="flex justify-between items-start">
          <div>
            <p class="text-gray-500 text-sm font-medium">总藏书量</p>
            <h3 class="text-3xl font-bold mt-1" id="total-books">0</h3>
            <p class="text-green-500 text-sm mt-2 flex items-center">
              <i class="fa fa-arrow-up mr-1"></i> 较上月增长 <span id="total-growth">12%</span>
            </p>
          </div>
          <div class="bg-primary/10 p-3 rounded-lg">
            <i class="fa fa-book text-primary text-xl"></i>
          </div>
        </div>
      </div>
      
      <div class="bg-white rounded-xl p-6 shadow-lg card-hover border-l-4 border-secondary">
        <div class="flex justify-between items-start">
          <div>
            <p class="text-gray-500 text-sm font-medium">本月借出</p>
            <h3 class="text-3xl font-bold mt-1" id="books-borrowed">0</h3>
            <p class="text-green-500 text-sm mt-2 flex items-center">
              <i class="fa fa-arrow-up mr-1"></i> 较上月增长 <span id="borrow-growth">8%</span>
            </p>
          </div>
          <div class="bg-secondary/10 p-3 rounded-lg">
            <i class="fa fa-share text-secondary text-xl"></i>
          </div>
        </div>
      </div>
      
      <div class="bg-white rounded-xl p-6 shadow-lg card-hover border-l-4 border-accent">
        <div class="flex justify-between items-start">
          <div>
            <p class="text-gray-500 text-sm font-medium">热门分类</p>
            <h3 class="text-3xl font-bold mt-1" id="popular-category">未知</h3>
            <p class="text-gray-500 text-sm mt-2">共 <span id="category-count">328</span> 本</p>
          </div>
          <div class="bg-accent/10 p-3 rounded-lg">
            <i class="fa fa-tags text-accent text-xl"></i>
          </div>
        </div>
      </div>
      
      <div class="bg-white rounded-xl p-6 shadow-lg card-hover border-l-4 border-amber-500">
        <div class="flex justify-between items-start">
          <div>
            <p class="text-gray-500 text-sm font-medium">逾期未还</p>
            <h3 class="text-3xl font-bold mt-1" id="overdue-books">0</h3>
            <p class="text-red-500 text-sm mt-2 flex items-center">
              <i class="fa fa-arrow-up mr-1"></i> 较上月增长 <span id="overdue-growth">3%</span>
            </p>
          </div>
          <div class="bg-amber-500/10 p-3 rounded-lg">
            <i class="fa fa-exclamation-triangle text-amber-500 text-xl"></i>
          </div>
        </div>
      </div>
    </div>
    <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
      <div class="bg-white rounded-xl shadow-lg p-6 chart-shadow">
        <div class="flex justify-between items-center mb-6">
          <h2 class="text-xl font-bold">图书分类统计</h2>
          <div class="flex space-x-2">
            <button class="text-sm px-3 py-1 bg-primary/10 text-primary rounded-md hover:bg-primary/20 transition-colors" onclick="refreshData()">
              刷新数据
            </button>
          </div>
        </div>
        <div class="h-[400px]" id="categoryChart"></div>
      </div>
      <div class="bg-white rounded-xl shadow-lg p-6 chart-shadow">
        <div class="flex justify-between items-center mb-6">
          <h2 class="text-xl font-bold">借阅趋势分析</h2>
          <div class="flex space-x-2">
            <button class="text-sm px-3 py-1 bg-primary/10 text-primary rounded-md hover:bg-primary/20 transition-colors" onclick="refreshData()">
              刷新数据
            </button>
          </div>
        </div>
        <div class="h-[400px]" id="borrowTrendChart"></div>
      </div>
    </div>
    <div class="mt-8 bg-white rounded-xl shadow-lg p-6 chart-shadow">
      <div class="flex justify-between items-center mb-6">
        <h2 class="text-xl font-bold">最新添加图书</h2>
        </button>
      </div>
      <div class="overflow-x-auto">
        <table class="min-w-full divide-y divide-gray-200">
          <thead>
            <tr>
              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">图书名称</th>
              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">分类</th>
              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">作者</th>
              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">添加日期</th>
              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">状态</th>
            </tr>
          </thead>
          <tbody class="bg-white divide-y divide-gray-200" id="latest-books">
          </tbody>
        </table>
      </div>
    </div>
  </main>

  <footer class="bg-dark text-white py-8">
    <div class="container mx-auto px-4">
      <div class="flex flex-col md:flex-row justify-between items-center">
        <div class="mb-4 md:mb-0">
          <div class="flex items-center space-x-2">
            <i class="fa fa-book text-primary text-xl"></i>
            <span class="font-bold text-lg">图书管理系统</span>
          </div>
          <p class="text-gray-400 mt-2 text-sm">智能、高效的图书馆管理解决方案</p>
        </div>
        <div class="flex space-x-6">
          <a href="#" class="text-gray-400 hover:text-white transition-colors">
            <i class="fa fa-github text-xl"></i>
          </a>
        </div>
      </div>
      <div class="border-t border-gray-800 mt-6 pt-6 text-center text-gray-400 text-sm">
        &copy; 2025 图书管理系统. 保留所有权利.
      </div>
    </div>
  </footer>

  <script>
    const random = {
      categories: ['文学', '计算机', '历史', '经济', '哲学', '科技', '教育', '医学'],
      range: (min, max) => Math.floor(Math.random() * (max - min + 1)) + min,
      status: () => Math.random() > 0.3 ? '可借阅' : '已借出',
      date: () => {
        const today = new Date();
        const daysAgo = this.range(1, 30);
        today.setDate(today.getDate() - daysAgo);
        return today.toISOString().split('T')[0];
      },
      book: () => ({
        name: `图书-${this.range(1, 1000)}`,
        category: this.categories[this.range(0, this.categories.length-1)],
        author: `作者-${this.range(1, 100)}`,
        date: this.date(),
        status: this.status()
      })
    };

    const categoryChart = echarts.init(document.getElementById('categoryChart'));
    const borrowTrendChart = echarts.init(document.getElementById('borrowTrendChart'));
    
    // 修改renderLatestBooks函数，从PHP接收数据
    function renderLatestBooks(books) {
      const tableBody = document.getElementById('latest-books');
      tableBody.innerHTML = '';
      
      books.forEach(book => {
        const row = document.createElement('tr');
        row.className = 'hover:bg-gray-50 transition-colors';
        const statusClass = book.status === '可借阅' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800';
        
        row.innerHTML = `
          <td class="px-6 py-4 whitespace-nowrap">
            <div class="flex items-center">
              <div class="flex-shrink-0 h-10 w-10 bg-primary/10 rounded-md flex items-center justify-center">
                <i class="fa fa-book text-primary"></i>
              </div>
              <div class="ml-4">
                <div class="text-sm font-medium text-gray-900">${book.name}</div>
              </div>
            </div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap">
            <div class="text-sm text-gray-900">${book.category}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap">
            <div class="text-sm text-gray-900">${book.author}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
            ${book.date}
          </td>
          <td class="px-6 py-4 whitespace-nowrap">
            <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${statusClass}">
              ${book.status}
            </span>
          </td>
        `;
        
        tableBody.appendChild(row);
      });
    }
    
    function generateRandomStats() {
      const total = random.range(500, 2000);
      const borrowed = random.range(50, 300);
      const overdue = random.range(10, 50);
      const growthRates = {
        total: random.range(-15, 20),
        borrow: random.range(-10, 15),
        overdue: random.range(-5, 8)
      };
      const popularIndex = random.range(0, random.categories.length-1);
      const popularCategory = random.categories[popularIndex];
      return {
        total,
        borrowed,
        overdue,
        growthRates,
        popularCategory,
        categoryCount: random.range(100, 500)
      };
    }

    function generateCategoryData() {
      const categoryCount = random.range(3, 8);
      const categories = random.categories
        .slice(0, categoryCount)
        .sort(() => 0.5 - Math.random());
      const counts = Array.from({length: categoryCount}, () => random.range(20, 200));
      return {categories, counts};
    }
    
    function generateBorrowTrendData() {
      const periods = random.range(5, 12);
      const dates = Array.from({length: periods}, (_, i) => 
        new Date(Date.now() - i * 24 * 60 * 60 * 1000).toLocaleDateString('zh-CN', { month: 'short', day: '2-digit' })
      );
      const borrows = Array.from({length: periods}, () => random.range(5, 50));
      const returns = Array.from({length: periods}, () => random.range(3, 30));
      return {dates, borrows, returns};
    }

    function updateCharts() {
      const categoryData = generateCategoryData();
      const borrowTrendData = generateBorrowTrendData();

      categoryChart.setOption({
        backgroundColor: 'transparent',
        color: ['#3b82f6', '#10b981', '#8b5cf6'],
        tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
        grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
        xAxis: { type: 'category', data: categoryData.categories, axisLabel: { color: '#64748b' } },
        yAxis: { type: 'value', axisLabel: { color: '#64748b' } },
        series: [{
          name: '图书数量',
          type: 'bar',
          barWidth: '60%',
          data: categoryData.counts,
          itemStyle: {
            borderRadius: 4,
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              { offset: 0, color: '#3b82f6' },
              { offset: 1, color: '#93c5fd' }
            ])
          },
          label: { show: true, position: 'top', color: '#334155' }
        }]
      });

      borrowTrendChart.setOption({
        backgroundColor: 'transparent',
        color: ['#3b82f6', '#10b981'],
        tooltip: { trigger: 'axis' },
        legend: { data: ['借出', '归还'], right: '10%', textStyle: { color: '#64748b' } },
        grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
        xAxis: { type: 'category', boundaryGap: false, data: borrowTrendData.dates, axisLabel: { color: '#64748b' } },
        yAxis: { type: 'value', axisLabel: { color: '#64748b' } },
        series: [
          {
            name: '借出',
            type: 'line',
            data: borrowTrendData.borrows,
            smooth: true,
            symbol: 'circle',
            symbolSize: 6,
            itemStyle: { color: '#3b82f6' },
            lineStyle: { width: 2 },
            areaStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: 'rgba(59, 130, 246, 0.4)' },
                { offset: 1, color: 'rgba(59, 130, 246, 0.05)' }
              ])
            }
          },
          {
            name: '归还',
            type: 'line',
            data: borrowTrendData.returns,
            smooth: true,
            symbol: 'circle',
            symbolSize: 6,
            itemStyle: { color: '#10b981' },
            lineStyle: { width: 2 },
            areaStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: 'rgba(16, 185, 129, 0.4)' },
                { offset: 1, color: 'rgba(16, 185, 129, 0.05)' }
              ])
            }
          }
        ]
      });
    }

    function updateStats() {
      const stats = generateRandomStats();
      
      animateNumber('total-books', 0, stats.total, 1500);
      animateNumber('books-borrowed', 0, stats.borrowed, 1500);
      animateNumber('overdue-books', 0, stats.overdue, 1500);
      
      document.getElementById('popular-category').textContent = stats.popularCategory;
      document.getElementById('category-count').textContent = stats.categoryCount;
      document.getElementById('total-growth').textContent = `${stats.growthRates.total}%`;
      document.getElementById('borrow-growth').textContent = `${stats.growthRates.borrow}%`;
      document.getElementById('overdue-growth').textContent = `${stats.growthRates.overdue}%`;
 
      setGrowthColor('total-growth', stats.growthRates.total);
      setGrowthColor('borrow-growth', stats.growthRates.borrow);
      setGrowthColor('overdue-growth', stats.growthRates.overdue);
    }

    function animateNumber(elementId, start, end, duration) {
      const element = document.getElementById(elementId);
      const range = end - start;
      const increment = end > start ? 1 : -1;
      const stepTime = Math.abs(Math.floor(duration / range));
      let current = start;
      
      const timer = setInterval(function() {
        current += increment;
        element.textContent = current.toLocaleString();
        if (current == end) {
          clearInterval(timer);
        }
      }, stepTime);
    }

    function setGrowthColor(elementId, value) {
      const element = document.getElementById(elementId);
      if (value > 0) {
        element.classList.add('text-green-500');
        element.classList.remove('text-red-500');
      } else {
        element.classList.add('text-red-500');
        element.classList.remove('text-green-500');
      }
    }

    // 刷新所有数据
    function refreshData() {
      updateStats();
      updateCharts();
      
      // 从PHP变量获取数据
      const books = <?php echo json_encode($randomBooks); ?>;
      renderLatestBooks(books);
    }

    // 监听窗口大小变化，自适应调整图表
    window.addEventListener('resize', function() {
      categoryChart.resize();
      borrowTrendChart.resize();
    });

    // 初始化页面
    document.addEventListener('DOMContentLoaded', function() {
      refreshData();
    });
  </script>
</body>
</html>